package com.martin.dms.hunit;

import java.io.InputStream;
import java.sql.Connection;

import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.ReplacementDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.connection.ConnectionProvider;
import org.hibernate.impl.SessionFactoryImpl;

import junit.framework.TestCase;

/**
 * A base test class for hibernate tests.
 * 
 * @author mtsvetkov
 */
public abstract class HibernateTestBase extends TestCase {

    private Session session;

    /**
     * Establishes a connection to the test data base and initializes test data. <br>
     * <br>
     * 
     * {@inheritDoc}
     */
    protected final void setUp() throws Exception {
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        ConnectionProvider connectionProvider = ((SessionFactoryImpl) sessionFactory).getSettings()
                .getConnectionProvider();
        Connection connection = connectionProvider.getConnection();
        IDatabaseConnection dbConnection = new DatabaseConnection(connection);

        InputStream datasetInput = getClass().getClassLoader().getResourceAsStream("init-dataset.xml");

        ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(datasetInput));
        dataSet.addReplacementObject("[null]", null);
        try {
            DatabaseOperation.CLEAN_INSERT.execute(dbConnection, dataSet);
        } finally {
            connectionProvider.closeConnection(connection);
        }

        session = sessionFactory.getCurrentSession();
        session.beginTransaction();
        session.getTransaction().commit();
        this.onSetUp();
    }

    /**
     * Gets a hibernate session from the hibernate SessionFactory.
     * 
     * @return the current opened hibernate session.
     */
    protected Session getSession() {
        if (!session.isOpen()) {
            session = HibernateUtil.getSessionFactory().getCurrentSession();
        }
        return session;
    }

    /**
     * Override this method to initialize test.
     * 
     * @throws Exception if error occurs.
     */
    protected abstract void onSetUp() throws Exception;
}
